FPS independent gameplay in Flash/Actionscript 3.0

12 May, 2013 @ 7:41:51 by

I’m currently developing a game for PC/MAC using Adobe Air and Actionscript 3.0 which has led me to test quite a few methods to achieve smooth gameplay. At first, i tried to use a timer instead of the enter_frame loop i often see because i’m more used to C / C++ and that is usually how you make a game loop in those languages. However, i soon found out that in Flash, the timers aren’t really fps independent. By testing my game in settings that lowered the frames per second (such as heavy population of hundreds of movieclips, software rendering, etc.), i discovered than even if i wasn’t relying on the ENTER_FRAME event for my updates, the gameplay would slow down to the point of being almost synchronized with the fps. That was a big issue and even though i managed to have the game really smooth at 60fps by using the GPU scaling (stage.fullScreenSourceRect), if a fps drop occured you would feel it gameplay wise.

For a video game, gameplay updates are what is really important. Smooth framerates are nice but hard to achieve because of the variety of configurations of the pc market. What should never be different on any computer is of course the gameplay, and this is why in other languages you usually update the screen and gameplay asynchronously. In Flash, there is no way to do this the way you would do it in…say, C++ for exemple. The best way to ensure the gameplay will be smooth is actually to use the ENTER_FRAME event listener and, inside the function called, check the time elapsed between updates. Once you’ve checked that time, you need to see if enough time has passed to allow for one or more updates to the gameplay. Or you can use the delta time (time difference between previous call and the current one) and pass it to your game objects to update them accordingly.

package
{
import flash.display.MovieClip;
import flash.utils.getTimer;
import flash.events.Event;

public class GameLoop extends MovieClip
{
  private var oldTime, newTime: int;
  private var frequency:int = 16;

  public function GameLoop()
  {
   addEventListener(Event.ADDED_TO_STAGE, initok);
  }

  private function initok(e:Event):void
  {
   newTime = 0;
   oldTime = getTimer();

   addEventListener(Event.ENTER_FRAME, loop);
  }

  private function loop(e:Event):void
  {
    newTime = getTimer();
    while (newTime >= oldTime + frequency)
    {
      oldTime += frequency;

      /* Gameplay logic */

    }
  }

OR
  private function loop(e:Event):void
  {
    newTime = getTimer();
    if (newTime >= oldTime + frequency)
    {
      var deltaTime:int = newTime - oldTime;

      /* Gameplay logic exemple */
      gameObject.update(deltaTime);

      oldTime = getTimer();

    }
  }


 }
}

And there you have it. It’s as simple as that. You can test it with a crappy fps set in your flash file and a better one. Gameplay wise, your game won’t be any different (unless you’re playing on a very old machine or doing intense computing inside the gameplay logic, but in that case you should probably try to optimize that anyway). Of course, since we’re relying on the ENTER_FRAME event, if you get less than 10fps the game will probably feel a bit choppy…but at least the gameplay will stay the same and it won’t change your game.

Hope this helps someone avoid the struggles i’ve been fighting against during this development.
Stay tuned for more and probably some game making tutorials in AS3, C++/SFML and other languages!